package plus.easydo.easyuc.web.config;

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.time.LocalDateTime;
import java.util.Optional;


/**
 * @author laoyu
 * @version 1.0
 * @date 2023-10-7
 */
@Slf4j
@Configuration
public class MybatisPlusConfig {



    /**
     * 分页插件
     *
     * @return MybatisPlusInterceptor
     * @author laoyu
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        //分页差插件
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
        return interceptor;
    }

    @Bean
    public MetaObjectHandler metaObjectHandler() {
        return new MyMetaObjectHandler();
    }

    /**
     * 自动填充审计、租户等信息。
     */
    public static class MyMetaObjectHandler implements MetaObjectHandler {
        @Override
        public void insertFill(MetaObject metaObject) {
            // 声明自动填充字段的逻辑。
            String userId = getCurrentUserId();
            String userName = getCurrentUserName();
            LocalDateTime now = LocalDateTime.now();

            //严格填充,只针对非主键的字段,只有该表注解了fill 并且 字段名和字段属性 能匹配到才会进行填充(null 值不填充)
            //严格模式,填充策略,默认有值不覆盖,如果提供的值为null也不填充
            strictInsertFill(metaObject, "createTime", LocalDateTime.class, now); //创建时间
            strictInsertFill(metaObject, "createBy", String.class, userId);       //创建人
            strictInsertFill(metaObject, "updateTime", LocalDateTime.class, now); //修改时间
            strictInsertFill(metaObject, "updateBy", String.class, userId);      //修改人
            strictInsertFill(metaObject, "createName", String.class, userName);      //创建人姓名

            String tenantId = MybatisPlusConfig.getTenantId();
            if (StringUtils.hasText(tenantId)) {
                strictInsertFill(metaObject, "tenantId", String.class, tenantId);  //租户
            }
        }

        @Override
        public void updateFill(MetaObject metaObject) {
            String userId = getCurrentUserId();
            LocalDateTime now = LocalDateTime.now();

            //不论是否外部设置了属性值，均改写
            setFieldValByName("updateTime", now, metaObject);
            setFieldValByName("updateBy", userId == null ? "" : userId, metaObject);
        }

        protected String getCurrentUserId() {
            try {
                return Optional.of((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes())
                        .map(ServletRequestAttributes::getRequest)
                        .map(req -> req.getHeader("HEADER_USER_ID_KEY"))
                        .orElse(null);
            } catch (Exception e) {
                log.warn("get current user id fail, message:{}", e.getMessage());
                return null;
            }
        }

        protected String getCurrentUserName() {
            try {
                return Optional.of((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes())
                        .map(ServletRequestAttributes::getRequest)
                        .map(req -> {
                            String userName = req.getHeader("HEADER_REALNAME_KEY");
                            return Optional.of(userName).orElse(null);
                        })
                        .orElse(null);
            } catch (Exception e) {
                log.warn("get current user name fail, message:{}", e.getMessage());
                return null;
            }
        }

    }

    public static String getTenantId() {
        return "default";
    }
}
